
# In[8]:


import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm

# 设置中文字体
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC", "Arial Unicode MS"]

# 定义目标花卉及其生物学参数
flowers = {
    '牡丹花': {'base_temp': 8, 'gdd_threshold': 500, 'bloom_days': 10},
    '油菜花': {'base_temp': 3, 'gdd_threshold': 400, 'bloom_days': 21},
    '杜鹃花': {'base_temp': 6, 'gdd_threshold': 420, 'bloom_days': 14}
}

# 定义目标城市及地理参数（仅保留需要的城市）
cities = {
    '洛阳': {'lat': 34.62, 'lon': 112.45, 'alt': 144, 'climate': 'temperate'},
    '婺源': {'lat': 29.25, 'lon': 117.86, 'alt': 120, 'climate': 'humid'},
    '毕节': {'lat': 27.30, 'lon': 105.29, 'alt': 1520, 'climate': 'temperate'}
}

# 花卉-城市映射关系
flower_city_mapping = {
    '牡丹花': '洛阳',
    '油菜花': '婺源',
    '杜鹃花': '毕节'
}

# 生成气象数据
def generate_weather_data(city, year):
    """生成指定城市和年份的每日气象数据"""
    date_range = pd.date_range(f'{year}-01-01', f'{year}-12-31')
    num_days = len(date_range)
    
    # 获取城市地理参数
    lat = cities[city]['lat']
    alt = cities[city]['alt']
    climate = cities[city]['climate']
    
    # 基础温度计算（考虑纬度和海拔）
    base_temp = 15 - alt/200  # 海拔修正
    
    # 生成温度数据（考虑季节性变化和随机波动）
    temps = []
    for day in date_range:
        # 季节性温度变化（正弦曲线）
        seasonal_temp = 10 * np.sin(2*np.pi*(day.dayofyear-80)/365)
        
        # 纬度修正（北方城市更冷）
        lat_correction = 0.5 * (lat - 30)/5
        
        # 随机波动
        random_fluctuation = np.random.normal(0, 2)
        
        # 综合温度
        temp = base_temp + seasonal_temp + lat_correction + random_fluctuation
        
        # 气候类型修正
        if climate == 'arid':
            temp += 2  # 干旱地区更热
        elif climate == 'humid':
            temp += 1  # 湿润地区温和
        
        temps.append(temp)
    
    return pd.DataFrame({
        'date': date_range,
        'temp': temps
    })

# 计算积温
def calculate_gdd(daily_temps, base_temp):
    """计算每日积温(GDD)"""
    gdd = []
    cumulative = 0
    for temp in daily_temps:
        daily_gdd = max(0, temp - base_temp)
        cumulative += daily_gdd
        gdd.append(cumulative)
    return gdd

# 预测花期
def predict_bloom_date(flower, city, year):
    """预测指定花卉在指定城市和年份的开花日期"""
    # 获取花卉参数
    base_temp = flowers[flower]['base_temp']
    gdd_threshold = flowers[flower]['gdd_threshold']
    
    # 生成气象数据
    weather_data = generate_weather_data(city, year)
    
    # 计算积温
    weather_data['gdd'] = calculate_gdd(weather_data['temp'], base_temp)
    
    # 找到积温达到阈值的日期
    threshold_reached = weather_data[weather_data['gdd'] >= gdd_threshold]
    
    if not threshold_reached.empty:
        # 首个达到积温阈值的日期
        bloom_date = threshold_reached.iloc[0]['date']
        return bloom_date
    else:
        # 如果全年积温未达到阈值，返回积温最高的日期
        max_gdd_idx = weather_data['gdd'].idxmax()
        return weather_data.loc[max_gdd_idx, 'date']

# 主程序：预测2026年指定花卉在对应城市的花期
def main():
    target_year = 2026
    results = []
    
    for flower, city in flower_city_mapping.items():
        # 预测开花日期
        bloom_date = predict_bloom_date(flower, city, target_year)
        
        # 计算花期结束日期
        bloom_days = flowers[flower]['bloom_days']
        end_date = bloom_date + timedelta(days=bloom_days)
        
        # 记录结果
        results.append({
            '花卉': flower,
            '城市': city,
            '预测开花日期': bloom_date.strftime('%Y-%m-%d'),
            '预测结束日期': end_date.strftime('%Y-%m-%d'),
            '花期长度(天)': bloom_days
        })
    
    # 转换为DataFrame并展示
    results_df = pd.DataFrame(results)
    print(f"{target_year}年花卉花期预测结果：")
    print(results_df)
    
    # 可视化结果
    visualize_results(results_df, target_year)

# 可视化预测结果
def visualize_results(results_df, year):
    """可视化花卉花期预测结果"""
    plt.figure(figsize=(10, 6))
    
    # 设置颜色
    colors = ['#FF5733', '#FFC300', '#DAF7A6']
    
    for i, (_, row) in enumerate(results_df.iterrows()):
        flower = row['花卉']
        city = row['城市']
        start_date = datetime.strptime(row['预测开花日期'], '%Y-%m-%d')
        end_date = datetime.strptime(row['预测结束日期'], '%Y-%m-%d')
        
        # 计算在年中的天数
        start_day = (start_date - datetime(year, 1, 1)).days
        end_day = (end_date - datetime(year, 1, 1)).days
        
        # 绘制花期线段
        plt.hlines(y=flower, xmin=start_day, xmax=end_day, 
                   linewidth=15, alpha=0.7, color=colors[i],
                   label=f"{flower} ({city})")
        
        # 添加日期标签
        plt.text(start_day, flower, f"{start_date.month}月{start_date.day}日", 
                 ha='right', va='center', fontsize=12, fontweight='bold')
        plt.text(end_day, flower, f"{end_date.month}月{end_date.day}日", 
                 ha='left', va='center', fontsize=12, fontweight='bold')
        
        # 添加城市名称
        plt.text((start_day + end_day)/2, flower, f"{city}", 
                 ha='center', va='bottom', fontsize=10, color='black')
    
    plt.title(f"{year}年花卉花期预测", fontsize=16)
    plt.xlabel("日期", fontsize=12)
    plt.ylabel("花卉", fontsize=12)
    plt.grid(True, alpha=0.3)
    plt.xlim(0, 365)
    plt.xticks([0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
              ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
              rotation=45)
    plt.legend(loc='upper right')
    
    plt.tight_layout()
    plt.show()

if __name__ == "__main__":
    main()


# In[ ]:




